/**
 * @author:albert
 * @date:2016年7月10日
 */
package com.bkbw.live.testclient;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Rectangle2D;
import java.net.InetSocketAddress;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bkbw.live.battle.database.DatabaseManager;
import com.bkbw.live.common.GameConfig;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BS2CBuyItemResp;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BS2CDropBagItemResp;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BS2CEquipNotify;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BS2CEquipResp;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.C2BSBuyItemReq;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.C2BSDropBagItemReq;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.C2BSEquipReq;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.HeadType;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.LoginNotify;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.LoginReq;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.LoginResp;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.LogoutNotify;
import com.bkbw.live.common.dataproto.CommonMessagePb.HashIntInt;
import com.bkbw.live.common.dataproto.CommonMessagePb.HashLongInt;
import com.bkbw.live.common.net.codec.NetCodecFactory;
import com.bkbw.live.common.net.codec.RawMessageObject;
import com.bkbw.live.common.util.Utils;
import com.google.protobuf.InvalidProtocolBufferException;


/**
 * @author albert
 *
 */
public class TestClientMain extends JFrame implements IMessageHandler {
	
	public static class TestConnector extends IoHandlerAdapter {
		IMessageHandler handler;
		private String host = "127.0.0.1";
		private int port = 8888;
		private SocketConnector connector;
		private IoSession session;
		public String getHost() {
			return host;
		}
		public void setHost(String host) {
			this.host = host;
		}
		public int getPort() {
			return port;
		}
		public void setPort(int port) {
			this.port = port;
		}
		public SocketConnector getConnector() {
			return connector;
		}
		public void setConnector(SocketConnector connector) {
			this.connector = connector;
		}
		public IoSession getSession() {
			return session;
		}
		public void setSession(IoSession session) {
			this.session = session;
		}
		
		public TestConnector(IMessageHandler handler) {
			this.handler = handler;
			this.connector = new NioSocketConnector();
			this.connector.getFilterChain().addLast("codec",
					new ProtocolCodecFilter(new NetCodecFactory()));
			this.connector.setHandler(this);
		}
		
		public boolean isConnected() {
			return ((this.session != null) && (this.session.isConnected()));
		}

		public void connect() {
			ConnectFuture connectFuture = this.connector
					.connect(new InetSocketAddress(this.host, this.port));
			connectFuture.awaitUninterruptibly(3000L);
			try {
				this.session = connectFuture.getSession();
			} catch (RuntimeIoException e) {
			}
		}

		public void disconnect() {
			if (this.session != null) {
				this.session.close(true).awaitUninterruptibly(3000L);
				this.session = null;
			}
		}

		@Override
		public void sessionOpened(IoSession session) throws Exception {
			handler.sessionOpened(session);
		}

		@Override
		public void sessionClosed(IoSession session) throws Exception {
			handler.sessionClosed(session);
		}
		
		@Override
		public void exceptionCaught(IoSession session, Throwable cause)
				throws Exception {
			handler.exceptionCaught(session, cause);
		}
		
		@Override
		public void messageReceived(IoSession session, Object message)
				throws Exception {
			handler.messageReceived(session, message);
		}
	}
	
	TestConnector connector = new TestConnector(this);
	
	Logger logger = LoggerFactory.getLogger(GameConfig.LoggerName);
	
	int gameId;
	int tableId;
	
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e) {

			e.printStackTrace();
		} catch (InstantiationException e) {

			e.printStackTrace();
		} catch (IllegalAccessException e) {

			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {

			e.printStackTrace();
		}
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					TestClientMain frame = new TestClientMain();
					frame.setLocationRelativeTo(null);
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	JPanel mainPanel;
	Font font;
	FontMetrics fontMetrics;
	
	public TestClientMain() {
		setResizable(false);

		setTitle(TestClientMain.class.getName());
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

		setBounds(100, 100, 600, 500);

		JPanel panel = new JPanel();
		getContentPane().add(panel, BorderLayout.CENTER);
		panel.setLayout(null); 
		mainPanel = panel;
		
		Font font=new Font("宋体",Font.BOLD,13);
		panel.setFont(font);
		this.setFont(font);
		this.font = font;
		
		init();
		initLoginUi();
		initBuyItemUi();
		initDropItemUi();
		initEquipUi();
		 
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				super.windowClosing(e);
				System.exit(0);
			}
		});
	}
	
	private void init() {
		connector.connect();
	}
	
	private boolean checkNetwork() {
		if (this.connector.isConnected()) {
			return true;
		}
		else {
			this.connector.connect();
			Toolkit.getDefaultToolkit().beep();
			JOptionPane.showMessageDialog(null, "网络连接没有建立", "信息",JOptionPane.INFORMATION_MESSAGE);
			return false;
		}
	}
	
	final int startx = 10;
	final int starty = 10;
	int line = starty;
	final int labelwidthCmd = 80;
	final int labelwidth = 50;
	final int labelheight = 20;
	final int textwidth = 100;
	final int textheight = 21;
	final int intervalx = 5;
	final int intervaly = 10;
	
	JTextField charIdTextField;
	JTextField allianceIdTextField;
	
	private void initLoginUi() {
		int posx = startx;
		int posy = line;
		
		//font = this.getFont();
		fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
		Rectangle2D rc = fontMetrics.getStringBounds("enter room:", this.getGraphics());
		System.out.println(rc);
		
		JLabel cmdlabel = new JLabel("enter room:");
		cmdlabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(cmdlabel);
		
		posx += rc.getWidth() + intervalx;
		rc = fontMetrics.getStringBounds("charId", this.getGraphics());
		JLabel charidLabel = new JLabel("charId");
		charidLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(charidLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		charIdTextField = new JTextField();
		charIdTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(charIdTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds("alliance", this.getGraphics());
		JLabel allianceLabel = new JLabel("alliance");
		allianceLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(allianceLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		allianceIdTextField = new JTextField();
		allianceIdTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(allianceIdTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds("enter", this.getGraphics());
		JButton button = new JButton("enter");
		button.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(button);
		button.addActionListener((ActionEvent e) -> {
			if (checkNetwork()) {
				logger.debug("ok");
				LoginReq.Builder reqBuilder = LoginReq.newBuilder();
				reqBuilder.setUserId(Integer.parseInt(charIdTextField.getText()));
				reqBuilder.setAllianceId(Integer.parseInt(allianceIdTextField.getText()));
				reqBuilder.setName("hello");
				LoginReq req = reqBuilder.build();
				RawMessageObject rawMessageObject = new RawMessageObject((short)HeadType.DUNGON_LOGIN_REQ_VALUE, 
						req.toByteArray(), this.connector.getSession());
				this.connector.getSession().write(rawMessageObject);
			}
			else {
				logger.debug("connect missed");
			}
		});
		line += labelheight + intervaly;
	}
	
	JTextField buyItemTextField;
	JTextField buyNumberTextField;
	private void initBuyItemUi() {
		int posx = startx;
		int posy = line;
		fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
		Rectangle2D rc = fontMetrics.getStringBounds("buy item:", this.getGraphics());
		System.out.println(rc);
		
		JLabel cmdlabel = new JLabel("buy item:");
		cmdlabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(cmdlabel);
		
		posx += rc.getWidth() + intervalx;
		rc = fontMetrics.getStringBounds("itemId", this.getGraphics());
		JLabel itemLabel = new JLabel("itemId");
		itemLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(itemLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		buyItemTextField = new JTextField();
		buyItemTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(buyItemTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds("number", this.getGraphics());
		JLabel numberLabel = new JLabel("number");
		numberLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(numberLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		buyNumberTextField = new JTextField();
		buyNumberTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(buyNumberTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds(" buy ", this.getGraphics());
		JButton button = new JButton(" buy ");
		button.setBounds(posx, posy, (int)rc.getWidth() + 1, labelheight);
		mainPanel.add(button);
		button.addActionListener((ActionEvent e) -> {
			if (checkNetwork()) {
				C2BSBuyItemReq.Builder reqBuilder = C2BSBuyItemReq.newBuilder();
				reqBuilder.setId(gameId);
				reqBuilder.setTableId(tableId);
				HashIntInt.Builder intintBuilder = HashIntInt.newBuilder();
				intintBuilder.setKey(Integer.parseInt(buyItemTextField.getText()));
				intintBuilder.setValue(Integer.parseInt(buyNumberTextField.getText()));
				reqBuilder.setBuyItems(intintBuilder.build());
				C2BSBuyItemReq req = reqBuilder.build();
				RawMessageObject rawMessageObject = new RawMessageObject((short)HeadType.C2BS_BUY_ITEM_REQ_VALUE, 
						req.toByteArray(), this.connector.getSession());
				this.connector.getSession().write(rawMessageObject);
			}
			else {
				logger.debug("connect missed");
			}
		});
		line += labelheight + intervaly;
	}
	
	

	JTextField dropItemTextField;
	JTextField dropNumberTextField;
	private void initDropItemUi() {
		int posx = startx;
		int posy = line;
		fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
		Rectangle2D rc = fontMetrics.getStringBounds("drop item:", this.getGraphics());
		System.out.println(rc);
		
		JLabel cmdlabel = new JLabel("drop item:");
		cmdlabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(cmdlabel);
		
		posx += rc.getWidth() + intervalx;
		rc = fontMetrics.getStringBounds("uid", this.getGraphics());
		JLabel itemLabel = new JLabel("uid");
		itemLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(itemLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		dropItemTextField = new JTextField();
		dropItemTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(dropItemTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds("number", this.getGraphics());
		JLabel numberLabel = new JLabel("number");
		numberLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(numberLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		dropNumberTextField = new JTextField();
		dropNumberTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(dropNumberTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds(" drop ", this.getGraphics());
		JButton button = new JButton(" drop ");
		button.setBounds(posx, posy, (int)rc.getWidth() + 1, labelheight);
		mainPanel.add(button);
		button.addActionListener((ActionEvent e) -> {
			if (checkNetwork()) {
				C2BSDropBagItemReq.Builder reqBuilder = C2BSDropBagItemReq.newBuilder();
				reqBuilder.setId(gameId);
				reqBuilder.setTableId(tableId);
				HashLongInt.Builder intintBuilder = HashLongInt.newBuilder();
				intintBuilder.setKey(Long.parseLong(dropItemTextField.getText()));
				intintBuilder.setValue(Integer.parseInt(dropNumberTextField.getText()));
				reqBuilder.addDropItems(intintBuilder.build());
				C2BSDropBagItemReq req = reqBuilder.build();
				RawMessageObject rawMessageObject = new RawMessageObject((short)HeadType.C2BS_DROP_BAG_ITEM_REQ_VALUE, 
						req.toByteArray(), this.connector.getSession());
				this.connector.getSession().write(rawMessageObject);
			}
			else {
				logger.debug("connect missed");
			}
		});
		line += labelheight + intervaly;
	}
	
	JTextField equipTextField;
	private void initEquipUi() {
		int posx = startx;
		int posy = line;
		fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
		Rectangle2D rc = fontMetrics.getStringBounds("equip item:", this.getGraphics());
		System.out.println(rc);
		
		JLabel cmdlabel = new JLabel("equipo item:");
		cmdlabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(cmdlabel);
		
		posx += rc.getWidth() + intervalx;
		rc = fontMetrics.getStringBounds("uid", this.getGraphics());
		JLabel itemLabel = new JLabel("uid");
		itemLabel.setBounds(posx, posy, (int)rc.getWidth(), labelheight);
		mainPanel.add(itemLabel);
		
		posx += (int)rc.getWidth() + intervalx;
		equipTextField = new JTextField();
		equipTextField.setBounds(posx, posy, textwidth, textheight);
		mainPanel.add(equipTextField);
		
		posx += textwidth + intervalx;
		rc = fontMetrics.getStringBounds(" equip ", this.getGraphics());
		JButton button = new JButton(" equip ");
		button.setBounds(posx, posy, (int)rc.getWidth() + 1, labelheight);
		mainPanel.add(button);
		button.addActionListener((ActionEvent e) -> {
			if (checkNetwork()) {
				C2BSEquipReq.Builder reqBuilder = C2BSEquipReq.newBuilder();
				reqBuilder.setId(gameId);
				reqBuilder.setTableId(tableId);
				reqBuilder.setUid(Long.parseLong(equipTextField.getText()));
				C2BSEquipReq req = reqBuilder.build();
				RawMessageObject rawMessageObject = new RawMessageObject((short)HeadType.C2BS_EQUIP_REQ_VALUE, 
						req.toByteArray(), this.connector.getSession());
				this.connector.getSession().write(rawMessageObject);
			}
			else {
				logger.debug("connect missed");
			}
		});
		line += labelheight + intervaly;
	}
	
	/* (non-Javadoc)
	 * @see com.bkbw.live.testclient.IMessageHandler#sessionOpened(org.apache.mina.core.session.IoSession)
	 */
	@Override
	public void sessionOpened(IoSession session) {
		// TODO Auto-generated method stub
		
	}

	/* (non-Javadoc)
	 * @see com.bkbw.live.testclient.IMessageHandler#sessionClosed(org.apache.mina.core.session.IoSession)
	 */
	@Override
	public void sessionClosed(IoSession session) {
		// TODO Auto-generated method stub
		
	}

	/* (non-Javadoc)
	 * @see com.bkbw.live.testclient.IMessageHandler#exceptionCaught(org.apache.mina.core.session.IoSession, java.lang.Throwable)
	 */
	@Override
	public void exceptionCaught(IoSession session, Throwable cause) {
		// TODO Auto-generated method stub
		
	}

	/* (non-Javadoc)
	 * @see com.bkbw.live.testclient.IMessageHandler#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object)
	 */
	@Override
	public void messageReceived(IoSession session, Object message) {
		// TODO Auto-generated method stub
		RawMessageObject rawMessageObject = (RawMessageObject)message;
		
		if (rawMessageObject.getHead() == (short)HeadType.DUNGON_LOGIN_RESP_VALUE) {
			try {
				LoginResp resp = LoginResp.parseFrom(rawMessageObject.getData());
				//Utils.dumpObject(resp);
				logger.debug(resp.toString());
				this.gameId = resp.getSelf().getId();
				this.tableId = resp.getTableId();
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == (short)HeadType.BS2C_BUY_ITEM_RESP_VALUE) {
			try {
				BS2CBuyItemResp resp = BS2CBuyItemResp.parseFrom(rawMessageObject.getData());
				logger.debug(resp.getClass()+resp.toString());
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == (short)HeadType.BS2C_DROP_BAG_ITEM_RESP_VALUE) {
			try {
				BS2CDropBagItemResp resp = BS2CDropBagItemResp.parseFrom(rawMessageObject.getData());
				logger.debug(resp.getClass()+resp.toString());
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == (short)HeadType.BS2C_EQUIP_RESP_VALUE) {
			try {
				BS2CEquipResp resp = BS2CEquipResp.parseFrom(rawMessageObject.getData());
				logger.debug(resp.getClass()+resp.toString());
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == (short)HeadType.BS2C_EQUIP_NOTIFY_VALUE) {
			try {
				BS2CEquipNotify resp = BS2CEquipNotify.parseFrom(rawMessageObject.getData());
				logger.debug(resp.getClass()+resp.toString());
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == (short)HeadType.DUNGON_LOGIN_NOTIFY_VALUE) {
			try {
				LoginNotify resp = LoginNotify.parseFrom(rawMessageObject.getData());
				logger.debug(resp.getClass()+resp.toString());
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == (short)HeadType.DUNGON_LOGOUT_NOTIFY_VALUE) {
			try {
				LogoutNotify resp = LogoutNotify.parseFrom(rawMessageObject.getData());
				logger.debug(resp.getClass()+resp.toString());
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		else if (rawMessageObject.getHead() == 0) {
			logger.debug("receive 0");
			logger.debug("receive head 0 datalen "+rawMessageObject.getData().length);
		}
	}
}
